package io.itit.ecp.admin.server.service.impl;

import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import icu.mhb.mybatisplus.plugln.base.service.impl.JoinServiceImpl;
import io.itit.ecp.admin.server.entity.*;
import io.itit.ecp.admin.server.mapper.*;
import io.itit.ecp.admin.server.service.ICarbonReductionForecastDataService;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;
import java.util.Objects;


@Service
@RequiredArgsConstructor
public class CarbonReductionForecastDataServiceImpl extends JoinServiceImpl<CarbonReductionForecastDataMapper, CarbonReductionForecastDataEntity>
        implements ICarbonReductionForecastDataService {

    private final EnergyForecastDataMapper energyForecastDataMapper;

    private final EmissionReductionFactorMapper emissionReductionFactorMapper;

    private final MeterDeviceMapper meterDeviceMapper;

    @Override
    @Transactional
    public void generateData(LocalDateTime start, LocalDateTime end) {
        List<EnergyForecastDataEntity> list = energyForecastDataMapper.selectList(new LambdaQueryWrapper<EnergyForecastDataEntity>()
                .ge(Objects.nonNull(start), EnergyForecastDataEntity::getSolidifyDate, start)
                .le(Objects.nonNull(end), EnergyForecastDataEntity::getSolidifyDate, end)
                .orderByDesc(EnergyForecastDataEntity::getSolidifyDate));
        for (EnergyForecastDataEntity dataEntity : list) {
            CarbonReductionForecastDataEntity energyEntity = getBaseMapper().selectOne(new LambdaQueryWrapper<CarbonReductionForecastDataEntity>()
                    .eq(CarbonReductionForecastDataEntity::getSceneProjectId, dataEntity.getSceneProjectId())
                    .eq(StringUtils.isNoneEmpty(dataEntity.getSceneEdificeId()), CarbonReductionForecastDataEntity::getSceneEdificeId, dataEntity.getSceneEdificeId())
                    .eq(StringUtils.isNoneEmpty(dataEntity.getSceneFloorId()), CarbonReductionForecastDataEntity::getSceneFloorId, dataEntity.getSceneFloorId())
                    .eq(StringUtils.isNoneEmpty(dataEntity.getSceneRoomId()), CarbonReductionForecastDataEntity::getSceneRoomId, dataEntity.getSceneRoomId())
                    .eq(CarbonReductionForecastDataEntity::getSolidifyDate, dataEntity.getSolidifyDate()));
            if (Objects.isNull(energyEntity)) {
                energyEntity = new CarbonReductionForecastDataEntity();
                energyEntity.setSceneProjectId(dataEntity.getSceneProjectId());
                energyEntity.setSceneEdificeId(dataEntity.getSceneEdificeId());
                energyEntity.setSceneFloorId(dataEntity.getSceneFloorId());
                energyEntity.setSceneRoomId(dataEntity.getSceneRoomId());
            }
            String meterDeviceId = dataEntity.getMeterDeviceId();
            MeterDeviceEntity deviceEntity = meterDeviceMapper.selectById(meterDeviceId);
            BigDecimal forecastValue = BigDecimal.ZERO;
            if (Objects.nonNull(deviceEntity)) {
                Date startDate = DateUtil.beginOfMonth(dataEntity.getSolidifyDate());
                Date endDate = DateUtil.endOfMonth(dataEntity.getSolidifyDate());
                List<EmissionReductionFactorEntity> factorEntities = emissionReductionFactorMapper.selectList(new LambdaQueryWrapper<EmissionReductionFactorEntity>()
                        .eq(EmissionReductionFactorEntity::getEnergyTypeId, deviceEntity.getEnergyTypeId())
                        .ge(EmissionReductionFactorEntity::getSolidifyDate, startDate)
                        .lt(EmissionReductionFactorEntity::getSolidifyDate, endDate)
                        .orderByDesc(EmissionReductionFactorEntity::getSolidifyDate));
                if (!factorEntities.isEmpty()) {
                    BigDecimal factor = factorEntities.get(0).getFactor();
                    if (Objects.nonNull(factor)) {
                        // 碳减=对应能源类型的碳减因子*对应能源类型的计量值
                        forecastValue = dataEntity.getMeterForecastValue().multiply(factor).setScale(2, RoundingMode.HALF_UP);
                    }
                }
            }
            energyEntity.setSolidifyDate(dataEntity.getSolidifyDate());
            energyEntity.setForecastValue(forecastValue);
            this.saveOrUpdate(energyEntity);
        }
    }
}
